home *** CD-ROM | disk | FTP | other *** search
Modula Implementation | 1994-09-22 | 11.6 KB | 399 lines |
- IMPLEMENTATION MODULE InOut;
-
- (* Input/output facilities as defined by N.Wirth *)
-
- (* Mostly, "local" comments in the text are either at the same line
- or just below the line(s) they concern. *)
-
-
- IMPORT Conversions, GEMDOS, FileSystem, Filename, Terminal;
- FROM SYSTEM IMPORT LONG, SHORT;
-
- TYPE String = ARRAY [0..80] OF CHAR;
- StKind = (string, line);
- (* selects ReadString or ReadLine: *)
-
- CONST BS = 10C; (* BackSpace *)
- LF = 12C; (* LineFeed *)
- CR = 15C; (* Carrige Return *)
- NUL = 0C; (* ASCII.NUL *)
-
- TYPE Stream = (FILE, (* file *)
- CON, (* screen and keyboard *)
- AUX, (* serial port (RS 232) *)
- PRN (* parallel port (printer *));
-
- VAR In, Out : Stream;
- InFile, OutFile : FileSystem.File;
-
- PROCEDURE RdStr (* called by ReadString and ReadLine *)
- (VAR s : ARRAY OF CHAR; (* The String *)
- VAR i : INTEGER; (* index of s,
- returned value:
- index of first element not read to *)
- kind : StKind (* select ReadString or ReadLine *) );
-
- VAR j, max : INTEGER;
- (* max is type INTEGER to be compatible to index i,
- which must be able to take the value -1 *)
- PROCEDURE Pt() : BOOLEAN; (* is actual element of s printable ? *)
- BEGIN
- IF kind = line THEN RETURN s[i]>=" " ELSE RETURN s[i]>" " END
- END Pt;
- BEGIN
- max:=HIGH(s);
- FOR j:=0 TO max DO s[j]:=NUL END; (* reset all elements of s *)
- i:=0;
- IF In=CON THEN
- Terminal.ReadString(s);
- WHILE ~Pt() DO INC(i) END;
- j:=0;
- WHILE (i<=max) & Pt() DO s[j]:=s[i]; INC(i); INC(j) END;
- i:=j;
- s[i]:=NUL;
- Done:=TRUE
- ELSE
- REPEAT Read(s[i]) UNTIL Pt() OR ~Done;
- (* skip leading not printable characters *)
- IF Done (* not end of file *) THEN
- LOOP
- INC(i);
- Done:=i<max; (* S[max] left for NUL *) IF ~Done THEN EXIT END;
- Read(s[i]); IF ~Done THEN EXIT END;
- IF ~Pt() (* not printable *) THEN EXIT END
- END (* LOOP *)
- END
- END;
- IF ~Done THEN s[i]:=NUL END;
- termCH:=s[i]; (* define termCH *)
- END RdStr;
-
- PROCEDURE Length (* of "short" string *)
- ( VAR S : ARRAY OF CHAR) : CARDINAL;
- VAR n : INTEGER;
- BEGIN
- n:=0;
- WHILE (S[n]>" ")&(n<HIGH(S))
- (* printable and not end of array S *)
- DO INC(n) END;
- IF S[n]>" "
- (* last element of S is printable, and length(string)=length(array *)
- THEN INC(n) END;
- RETURN n
- END Length;
-
- PROCEDURE equ( S, T : ARRAY OF CHAR) : BOOLEAN;
- (* "short" string S = "short" string T *)
- VAR n : CARDINAL;
- BEGIN
- IF Length(S)#Length(T) THEN RETURN FALSE END;
- (* False if the two length are not equal *)
- FOR n:=0 TO Length(S)-1 DO
- IF S[n]#T[n] THEN RETURN FALSE END
- (* False if any two elemnts with same indices are different *)
- END;
- RETURN TRUE (* all elements are equal *)
- END equ;
-
- PROCEDURE ReqName(VAR name : ARRAY OF CHAR);
- (* request a stream name;
- called by the Open... procedures *)
- VAR
- F, Fn : Filename.filename;
- i : INTEGER;
- j : CARDINAL;
- Wild, Point : BOOLEAN;
- BEGIN
- FOR j:=0 TO Length(name) DO
- IF (name[j]=':') & (i#1) THEN name[j]:='?' END;
- (* leave only ':' at second position of name *)
- CASE name[j] OF
- 0C .. ')' : name[j]:='?'; |
- '+' .. '-' : name[j]:='?'; |
- '/' : name[j]:='?'; |
- ';' .. '@' : name[j]:='?'; |
- '[' : name[j]:='?'; |
- ']' .. '^' : name[j]:='?'; |
- 140C : name[j]:='?'; |
- '{' ..177C : name[j]:='?'; |
- 233C..237C : name[j]:='?'; |
- 246C..257C : name[j]:='?'; |
- 271C..277C : name[j]:='?'; |
- 302C..377C : name[j]:='?'
- ELSE
- (* leave only digits, letters, '_', '*', '?', '.', ':', and '\' *)
- END
- END;
- Point:=FALSE;
- FOR j:=Length(name) TO 0 BY -1 DO
- IF Point & (name[j]='.') THEN name[j]:='?' END;
- Point:=(Point OR (name[j]='.')) & (name[j]#'\')
- (* leave only one '.' per (folder-)name *)
- END;
- Filename.GetDriveAndPath(Fn);
- Filename.parse(name,F);
- Fn.name:='*';
- Filename.compose(F,Fn,name);
- i:=0;
- REPEAT
- Wild:=(name[i]='*') OR (name[i]='?');
- INC(i);
- UNTIL (i>HIGH(name)) OR Wild OR (name[i]<=' ');
- IF ~Wild THEN Done:= TRUE; RETURN END;
- Filename.parse(name,F);
- Fn:=F;
- IF (Fn.name[0]='*')&(Fn.name[1]=NUL) THEN Fn.name:='TEST' END;
- Filename.SelectFilename(F,Fn,Done);
- Done:=~Done;
- Filename.compose(Fn,Fn,name);
- END ReqName;
-
- PROCEDURE ConvFromStr ( s : ARRAY OF CHAR;
- VAR res : LONGCARD;
- max : LONGCARD;
- neg : BOOLEAN;
- VAR Done : BOOLEAN);
- VAR L,b : CARDINAL;
- BEGIN
- L:=Length(s);
- Done:=L>0;
- IF Done THEN
- CASE s[L-1] OF
- 'H': b:=10H; s[L-1]:=NUL; |
- 'C': b:=10B; s[L-1]:=NUL; |
- 'B': b:=10B; s[L-1]:=NUL; |
- ELSE
- b:=10; s[L]:=NUL
- END;
- Conversions.ConvertFromString(s,b,neg,max,res,Done)
- END
- END ConvFromStr;
-
- TYPE ReadyProc = PROCEDURE() : BOOLEAN;
-
- PROCEDURE Ready(R : ReadyProc) : BOOLEAN;
- VAR n : CARDINAL;
- BEGIN
- n:=0;
- REPEAT
- IF R() THEN RETURN TRUE END;
- INC(n)
- UNTIL n=10000;
- RETURN FALSE
- END Ready;
-
- PROCEDURE OpenInput (name : ARRAY OF CHAR );
- BEGIN
- CloseInput; (* close current In *)
- IF Done THEN
- IF equ("CON:",name) THEN
- In:=CON;
- Done:=TRUE
- ELSIF equ("AUX:",name) THEN
- Done:=Ready(GEMDOS.AuxIS);
- IF Done THEN In:=AUX END
- ELSIF equ("PRN:",name) THEN
- Done:=FALSE (* no input from PRN *)
- ELSE
- ReqName(name);
- FileSystem.Lookup(InFile,name,FALSE);
- Done:=InFile.length>LONG(0);
- IF ~Done THEN FileSystem.Delete(InFile) ELSE In:=FILE END
- END
- END;
- IF ~Done THEN (* select default In *) In:=CON END
- END OpenInput;
-
- PROCEDURE OpenOutput ( name : ARRAY OF CHAR );
- BEGIN
- CloseOutput;
- IF Done THEN
- IF equ("CON:",name) THEN
- Out:=CON;
- Done:=TRUE
- ELSIF equ("AUX:",name) THEN
- Done:=Ready(GEMDOS.AuxOS);
- IF Done THEN Out:=AUX END
- ELSIF equ("PRN:",name) THEN
- Done:=Ready(GEMDOS.PrnOS);
- IF Done THEN Out:=PRN END
- ELSE
- ReqName(name);
- FileSystem.Lookup(OutFile,name,TRUE);
- Out:=FILE
- END
- END;
- IF ~Done THEN (* select default Out *) Out:=CON END
- END OpenOutput;
-
- PROCEDURE CloseInput;
- VAR reply : INTEGER;
- BEGIN
- IF Out=FILE THEN FileSystem.Close(OutFile) END;
- In:=CON; (* return In to default value *)
- Done:=TRUE
- END CloseInput;
-
- PROCEDURE CloseOutput;
- VAR reply : INTEGER;
- BEGIN
- CASE Out OF
- AUX..PRN: WriteLn; | (* Empties the buffer *)
- FILE: FileSystem.Close(OutFile) |
- ELSE
- END;
- Done:=TRUE;
- Out:=CON (* return Out to default value *)
- END CloseOutput;
-
- PROCEDURE Read(VAR ch : CHAR);
- BEGIN
- CASE In OF
- FILE: Done:=~InFile.eof;
- IF Done THEN FileSystem.ReadChar(InFile,ch) END; |
- CON: Terminal.Read(ch); |
- AUX: Done:=Ready(GEMDOS.AuxIS);
- IF Done THEN GEMDOS.AuxIn(ch) END; |
- PRN: Done:=FALSE
- END;
- IF ~Done THEN ch:=NUL END
- END Read;
-
- PROCEDURE ReadString ( VAR s : ARRAY OF CHAR );
- VAR i : INTEGER; (* index of s *)
- BEGIN
- RdStr(s, i, string (* select ReadString *) )
- END ReadString;
-
- PROCEDURE ReadLine ( VAR s : ARRAY OF CHAR );
- VAR i : INTEGER; (* index of s *)
- BEGIN
- RdStr(s, i, line (* select ReadLine *) );
- s[i]:=NUL; (* to make s compatible to WriteString *)
- termCH:=NUL
- END ReadLine;
-
- PROCEDURE ReadInt ( VAR x : INTEGER );
- VAR S : String;
- res : RECORD
- CASE : BOOLEAN OF
- TRUE : C : LONGCARD |
- FALSE: I : LONGINT
- END
- END;
- BEGIN
- ReadString(S);
- IF Done THEN
- ConvFromStr( S, res.C, MAX(INTEGER), TRUE, Done);
- IF Done THEN x:=SHORT(res.I) END
- END
- (* convert S, terminated by termCH, to Integer x and report success *)
- END ReadInt;
-
- PROCEDURE ReadCard ( VAR x : CARDINAL );
- VAR S : String;
- res : LONGCARD;
- BEGIN
- ReadString(S);
- IF Done THEN
- ConvFromStr( S, res, MAX(CARDINAL), FALSE, Done);
- IF Done THEN x:=SHORT(res) END
- END
- (* convert S, terminated by termCH, to Cardinal x and report success *)
- END ReadCard;
-
- PROCEDURE Write ( ch : CHAR );
- BEGIN
- CASE Out OF
- FILE: FileSystem.WriteChar(OutFile,ch);
- Done:=TRUE; |
- AUX : Done:=Ready(GEMDOS.AuxOS);
- IF Done THEN GEMDOS.AuxOut(ch) END; |
- CON : Terminal.Write(ch);
- Done:=TRUE; |
- PRN : Done:=Ready(GEMDOS.PrnOS);
- IF Done THEN GEMDOS.PrnOut(ch) END
- END
- END Write;
-
- PROCEDURE WriteLn;
- BEGIN
- Write(CR);
- Write(LF)
- END WriteLn;
-
- PROCEDURE WriteString ( s : ARRAY OF CHAR );
- VAR i : INTEGER;
- BEGIN
- i:=0;
- WHILE (i<=HIGH(s))&(s[i]#NUL)
- (* stop writing if s is exhausted or "default termCH" is found *)
- DO
- IF s[i]>=" " (* s[i] is printable *) THEN Write(s[i]) END;
- INC(i) (* next index *)
- END
- END WriteString;
-
- PROCEDURE WriteStringRight ( s : ARRAY OF CHAR ; n : INTEGER);
- VAR L : INTEGER;
- BEGIN
- L:=Length(s);
- IF n>L THEN
- IF n>HIGH(s) THEN n:=HIGH(s) END;
- INC(n); INC(L);
- WHILE L>0 DO s[n-1]:=s[L-1]; DEC(n); DEC(L) END;
- WHILE n>0 DO s[n-1]:=' '; DEC(n) END
- END;
- WriteString(s)
- END WriteStringRight;
-
- PROCEDURE WriteInt ( x : INTEGER ; n : CARDINAL );
- VAR S : String;
- Dummy : BOOLEAN;
- BEGIN
- Conversions.ConvertToString(ABS(x),10,x<0,S,Dummy);
- (* convert integer x to string S *)
- WriteStringRight(S,n)
- END WriteInt;
-
- PROCEDURE WriteCard ( x, n : CARDINAL );
- VAR S : String;
- Dummy : BOOLEAN;
- BEGIN
- Conversions.ConvertToString(x,10,FALSE,S,Dummy);
- (* convert cardinal x to string S *)
- WriteStringRight(S,n)
- END WriteCard;
-
- PROCEDURE WriteOct ( x, n : CARDINAL );
- VAR S : String;
- L : CARDINAL;
- Dummy : BOOLEAN;
- BEGIN
- Conversions.ConvertToString(x,10B,FALSE,S,Dummy);
- L:=Length(S);
- S[L] :='B';
- S[L+1]:=NUL;
- (* convert cardinal x to string S (octal) *)
- WriteStringRight(S,n)
- END WriteOct;
-
- PROCEDURE WriteHex ( x, n : CARDINAL );
- VAR S : String;
- L : CARDINAL;
- Dummy : BOOLEAN;
- BEGIN
- Conversions.ConvertToString(x,10H,FALSE,S,Dummy);
- L:=Length(S);
- S[L] :='H';
- S[L+1]:=NUL;
- (* convert cardinal x to string S (Hexadecimal) *)
- WriteStringRight(S,n)
- END WriteHex;
-
- BEGIN
-
- In := CON; Out := CON; (* Initialise In=keyboard and Out=screen *)
-
- END (* IMPLEMENTATION MODULE *) InOut.
-